package com.ruoyi.project.platform.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSON;
import com.ruoyi.project.platform.agent.GiteeAgent;
import com.ruoyi.project.platform.domain.StyParameter;
import com.ruoyi.project.platform.dto.StrategyDto;
import com.ruoyi.project.platform.mapper.StyParameterMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.project.platform.mapper.StyStrategyMapper;
import com.ruoyi.project.platform.domain.StyStrategy;
import com.ruoyi.project.platform.service.IStyStrategyService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 策略Service业务层处理
 *
 * @author ruoyi
 * @date 2020-07-23
 */
@Slf4j
@Service
public class StyStrategyServiceImpl implements IStyStrategyService {
    @Autowired
    GiteeAgent giteeAgent;
    @Autowired
    private StyStrategyMapper styStrategyMapper;
    @Autowired
    private StyParameterMapper styParameterMapper;

    /**
     * 查询策略
     *
     * @param strategyId 策略ID
     * @return 策略
     */
    @Override
    public StyStrategy selectStyStrategyById(Long strategyId) {
        return styStrategyMapper.selectStyStrategyById(strategyId);
    }

    /**
     * 查询策略列表
     *
     * @param styStrategy 策略
     * @return 策略
     */
    @Override
    public List<StyStrategy> selectStyStrategyList(StyStrategy styStrategy) {
        return styStrategyMapper.selectStyStrategyList(styStrategy);
    }

    /**
     * 新增策略
     *
     * @param styStrategy 策略
     * @return 结果
     */
    @Override
    public int insertStyStrategy(StyStrategy styStrategy) {
        return styStrategyMapper.insertStyStrategy(styStrategy);
    }

    /**
     * 修改策略
     *
     * @param styStrategy 策略
     * @return 结果
     */
    @Override
    public int updateStyStrategy(StyStrategy styStrategy) {
        return styStrategyMapper.updateStyStrategy(styStrategy);
    }

    /**
     * 批量删除策略
     *
     * @param strategyIds 需要删除的策略ID
     * @return 结果
     */
    @Override
    public int deleteStyStrategyByIds(Long[] strategyIds) {
        return styStrategyMapper.deleteStyStrategyByIds(strategyIds);
    }

    /**
     * 删除策略信息
     *
     * @param strategyId 策略ID
     * @return 结果
     */
    @Override
    public int deleteStyStrategyById(Long strategyId) {
        return styStrategyMapper.deleteStyStrategyById(strategyId);
    }

    @Override
    @Transactional
    public int syncParameter(StrategyDto.SyncInfo info) {
        List<List<String>> params = giteeAgent.syncParameterWithTag(info.getTag());
        if (params.isEmpty()) {
            log.warn("sync param is empty with tag {}", JSON.toJSONString(info));
        } else {
            StyStrategy condition = new StyStrategy();
            condition.setPath(info.getPath());
            List<StyStrategy> result = styStrategyMapper.selectStyStrategyList(condition);
            if (result.isEmpty()) {
                log.warn("sync stystrategy is not exists with info {}", JSON.toJSONString(info));
            } else if (result.size() != 1) {
                log.warn("sync stystrategy too many but should be only one {}", JSON.toJSONString(info));
            } else {
                StyStrategy toBeUpdate = result.get(0);
                toBeUpdate.setImage(info.getImage());
                toBeUpdate.setTagVersion(info.getTag());
                styStrategyMapper.updateStyStrategy(toBeUpdate);
                Map<String, List<String>> paramTemp = new HashMap<>();
                params.forEach(m -> {
                    String paramName = m.get(0);
                    paramTemp.put(paramName, m);

                    String paramDesc = m.get(1);
                    String paramDefault = m.get(2);
                    StyParameter conditionParam = new StyParameter();
                    conditionParam.setStrategyId(toBeUpdate.getStrategyId());
                    conditionParam.setName(paramName);
                    List<StyParameter> parameterToUpdate = styParameterMapper.selectStyParameterList(conditionParam);
                    if (parameterToUpdate.isEmpty()) {
                        StyParameter toSave = new StyParameter();
                        toSave.setStrategyId(toBeUpdate.getStrategyId());
                        toSave.setName(paramName);
                        toSave.setDescription(paramDesc);
                        toSave.setDefaultValue(paramDefault);
                        styParameterMapper.insertStyParameter(toSave);
                    } else if (parameterToUpdate.size() != 1) {
                        log.warn("parameter should be only one {}", JSON.toJSONString(m));
                    } else {
                        StyParameter toUp = parameterToUpdate.get(0);
                        if (!toUp.getDescription().equals(paramDesc) || !toUp.getDefaultValue().equals(paramDefault)) {
                            toUp.setDefaultValue(paramDefault);
                            toUp.setDescription(paramDesc);
                            styParameterMapper.updateStyParameter(toUp);
                        }
                    }
                });
                StyParameter conditionParam = new StyParameter();
                conditionParam.setStrategyId(toBeUpdate.getStrategyId());
                List<StyParameter> parameterToUpdate = styParameterMapper.selectStyParameterList(conditionParam);
                if (!parameterToUpdate.isEmpty()) {
                    List<Long> toDelete = new ArrayList<>();
                    parameterToUpdate.forEach(m -> {
                        if (!paramTemp.containsKey(m.getName())) toDelete.add(m.getParameterId());
                    });
                    if (!toDelete.isEmpty())
                        styParameterMapper.deleteStyParameterByIds(toDelete.toArray(new Long[toDelete.size()]));
                }

            }
        }
        return 0;
    }
}
